Prep for soft reboots.
Signed-off-by: Colin Walters <walters@verbum.org>
#include <errno.h>
#include <ostree-core.h>
#include <ostree-repo-private.h>
+#include <sys/mount.h>
#ifdef HAVE_COMPOSEFS
#include <libcomposefs/lcfs-mount.h>
#define BINDING_KEYPATH "/etc/ostree/initramfs-root-binding.key"
// The kernel argument to configure composefs
#define CMDLINE_KEY_COMPOSEFS "ostree.prepare-root.composefs"
+// The key in the config for etc
+#define ETC_KEY "etc"
static bool
proc_cmdline_has_key_starting_with (const char *cmdline, const char *key)
#endif
+/**
+ * otcore_mount_etc:
+ *
+ * Mount /etc for a deployment, assuming that the current process working directory is the source.
+ */
+gboolean
+otcore_mount_etc (GKeyFile *config, GVariantBuilder *metadata_builder, const char *mount_target,
+ GError **error)
+{
+ gboolean etc_transient = FALSE;
+ if (!ot_keyfile_get_boolean_with_default (config, ETC_KEY, OTCORE_PREPARE_ROOT_TRANSIENT_KEY,
+ FALSE, &etc_transient, error))
+ return glnx_prefix_error (error, "Failed to parse etc.transient value");
+
+ g_autofree char *target_etc = g_build_filename (mount_target, "etc", NULL);
+ if (etc_transient)
+ {
+ const char *ovldir = "/run/ostree/transient-etc";
+
+ g_variant_builder_add (metadata_builder, "{sv}", OTCORE_RUN_BOOTED_KEY_TRANSIENT_ETC,
+ g_variant_new_string (ovldir));
+
+ // Our lower directory is usr/etc.
+ g_autofree char *lowerdir = g_build_filename (mount_target, "usr/etc", NULL);
+ // Standard overlayfs tempdirs
+ g_autofree char *upperdir = g_build_filename (ovldir, "upper", NULL);
+ g_autofree char *workdir = g_build_filename (ovldir, "work", NULL);
+
+ struct
+ {
+ const char *path;
+ int mode;
+ } subdirs[] = { { ovldir, 0700 }, { upperdir, 0755 }, { workdir, 0755 } };
+ for (int i = 0; i < G_N_ELEMENTS (subdirs); i++)
+ {
+ if (mkdirat (AT_FDCWD, subdirs[i].path, subdirs[i].mode) < 0)
+ return glnx_throw_errno_prefix (error, "Failed to create dir %s", subdirs[i].path);
+ }
+
+ g_autofree char *ovl_options
+ = g_strdup_printf ("lowerdir=%s,upperdir=%s,workdir=%s", lowerdir, upperdir, workdir);
+ if (mount ("overlay", target_etc, "overlay", MS_SILENT, ovl_options) < 0)
+ return glnx_throw_errno_prefix (error, "failed to mount transient etc overlayfs");
+ }
+ else
+ {
+ /* Bind-mount /etc (at deploy path), and remount as writable. */
+ if (mount ("etc", target_etc, NULL, MS_BIND | MS_SILENT, NULL) < 0)
+ return glnx_throw_errno_prefix (error, "failed to prepare /etc bind-mount at %s",
+ target_etc);
+ if (mount (target_etc, target_etc, NULL, MS_BIND | MS_REMOUNT | MS_SILENT, NULL) < 0)
+ return glnx_throw_errno_prefix (error, "failed to make writable /etc bind-mount at %s",
+ target_etc);
+ }
+ return TRUE;
+}
+
gboolean
otcore_mount_rootfs (ComposefsConfig *composefs_config, GVariantBuilder *metadata_builder,
gboolean root_transient, const char *root_mountpoint, const char *deploy_path,
const char *deploy_path, const char *mount_target,
bool *out_using_composefs, GError **error);
+gboolean otcore_mount_etc (GKeyFile *config, GVariantBuilder *metadata_builder,
+ const char *mount_target, GError **error);
+
// Our directory with transient state (eventually /run/ostree-booted should be a link to
// /run/ostree/booted)
#define OTCORE_RUN_OSTREE "/run/ostree"
#define OTCORE_PREPARE_ROOT_COMPOSEFS_KEY "composefs"
#define OTCORE_PREPARE_ROOT_ENABLED_KEY "enabled"
#define OTCORE_PREPARE_ROOT_KEYPATH_KEY "keypath"
+#define OTCORE_PREPARE_ROOT_TRANSIENT_KEY "transient"
// The file written in the initramfs which contains an a{sv} of metadata
// from ostree-prepare-root.
/* This key configures the / mount in the deployment root */
#define ROOT_KEY "root"
-#define ETC_KEY "etc"
-#define TRANSIENT_KEY "transient"
#define OSTREE_PREPARE_ROOT_DEPLOYMENT_MSG \
SD_ID128_MAKE (71, 70, 33, 6a, 73, ba, 46, 01, ba, d3, 1a, f8, 88, aa, 0d, f7)
gboolean sysroot_readonly = FALSE;
gboolean root_transient = FALSE;
- if (!ot_keyfile_get_boolean_with_default (config, ROOT_KEY, TRANSIENT_KEY, FALSE, &root_transient,
- &error))
+ if (!ot_keyfile_get_boolean_with_default (config, ROOT_KEY, OTCORE_PREPARE_ROOT_TRANSIENT_KEY,
+ FALSE, &root_transient, &error))
return FALSE;
// We always parse the composefs config, because we want to detect and error
* the deployment needs to be created and remounted as read/write. */
if (sysroot_readonly || using_composefs || root_transient)
{
- gboolean etc_transient = FALSE;
- if (!ot_keyfile_get_boolean_with_default (config, ETC_KEY, TRANSIENT_KEY, FALSE,
- &etc_transient, &error))
- errx (EXIT_FAILURE, "Failed to parse etc.transient value: %s", error->message);
-
- static const char *tmp_sysroot_etc = TMP_SYSROOT "/etc";
- if (etc_transient)
- {
- char *ovldir = "/run/ostree/transient-etc";
-
- g_variant_builder_add (&metadata_builder, "{sv}", OTCORE_RUN_BOOTED_KEY_TRANSIENT_ETC,
- g_variant_new_string (ovldir));
-
- char *lowerdir = "usr/etc";
- if (using_composefs)
- lowerdir = TMP_SYSROOT "/usr/etc";
-
- g_autofree char *upperdir = g_build_filename (ovldir, "upper", NULL);
- g_autofree char *workdir = g_build_filename (ovldir, "work", NULL);
-
- struct
- {
- const char *path;
- int mode;
- } subdirs[] = { { ovldir, 0700 }, { upperdir, 0755 }, { workdir, 0755 } };
- for (int i = 0; i < G_N_ELEMENTS (subdirs); i++)
- {
- if (mkdirat (AT_FDCWD, subdirs[i].path, subdirs[i].mode) < 0)
- err (EXIT_FAILURE, "Failed to create dir %s", subdirs[i].path);
- }
-
- g_autofree char *ovl_options
- = g_strdup_printf ("lowerdir=%s,upperdir=%s,workdir=%s", lowerdir, upperdir, workdir);
- if (mount ("overlay", tmp_sysroot_etc, "overlay", MS_SILENT, ovl_options) < 0)
- err (EXIT_FAILURE, "failed to mount transient etc overlayfs");
- }
- else
- {
- /* Bind-mount /etc (at deploy path), and remount as writable. */
- if (mount ("etc", tmp_sysroot_etc, NULL, MS_BIND | MS_SILENT, NULL) < 0)
- err (EXIT_FAILURE, "failed to prepare /etc bind-mount at /sysroot.tmp/etc");
- if (mount (tmp_sysroot_etc, tmp_sysroot_etc, NULL, MS_BIND | MS_REMOUNT | MS_SILENT, NULL)
- < 0)
- err (EXIT_FAILURE, "failed to make writable /etc bind-mount at /sysroot.tmp/etc");
- }
+ if (!otcore_mount_etc (config, &metadata_builder, TMP_SYSROOT, &error))
+ errx (EXIT_FAILURE, "Failed to mount etc: %s", error->message);
}
/* Prepare /usr.